home *** CD-ROM | disk | FTP | other *** search
/ No Fragments Archive 12: Textmags & Docs / nf_archive_12.iso / MAGS / SOURCES / ATARI_SRC.ZIP / atari source / AHDI / TSTDRIVE / IDE.S < prev    next >
Encoding:
Text File  |  2001-02-09  |  24.3 KB  |  898 lines

  1. ;+
  2. ; Edit History
  3. ;
  4. ; Sep-05-90    ml.    Created this for drives on the IDE bus.
  5. ;
  6. ; Mar-28-91    ml.    Do not use the IDE Sector Count Register 
  7. ;            to count down mulitiple sectors read or
  8. ;            write.  Some vendors (e.g. Conner and 
  9. ;            Seagate) seem to update this register 
  10. ;            too early, and every now and then, the
  11. ;            last sector of data would remain in the
  12. ;            internal sector buffer.  
  13. ;            
  14. ;            Code in ideread() and idewrite() are modified
  15. ;            not to use the IDE Sector Count Register.
  16. ;
  17. ; Aug-16-91    ml.    W4int() has been modified, in the case of
  18. ;            an error occurred, to return value in the 
  19. ;            Status register for driver code, and return 
  20. ;            value in the Error register for non-driver
  21. ;            code.
  22. ;
  23. ; Oct-10-91    ml.    Special-cased Conner drives for fmtunt() to
  24. ;            set drive to appropiate mode.  Added setmode().
  25. ;
  26. ; Oct-11-91    ml.    Special-cased Conner drives for read and write
  27. ;            to get current drive parameters.  Added gcparm().
  28. ;
  29. ; Mar-03-92    ml.    Added code to test if a drive exist on the IDE bus.
  30. ;-
  31.  
  32. .include    "defs.h"
  33. .include    "sysvar.h"
  34. .include    "mfp.h"
  35. .include    "error.h"
  36. .include    "ide.h"
  37. .include    "blitter.h"
  38.  
  39. .extern    _useblit
  40.  
  41. ;+
  42. ; Wait for status to come back
  43. ;-
  44. w4int:    move.l    #D_WORST,d0    ; d0 = timeout limit
  45.     add.l    _hz_200,d0    ; d0 = expiration time
  46. .0:    btst.b    #5,GPIP        ; interrupt?
  47.     beq.s    .1        ; if so, out of the loop
  48.     cmp.l    _hz_200,d0    ; timeout?
  49.     bhi.s    .0        ; if not, wait some more
  50.     moveq    #$ff,d0        ; else, return timeout
  51.     bra.s    .3
  52. .1:    moveq    #0,d0        ; clear d0
  53.     move.b    IDESR,d0    ; d0.b = status returned
  54.     btst    #ERR,d0        ; any error?
  55.  
  56. .if    !DRIVER            ; for non-driver code
  57.     beq.s    .2        ; if no error, go on
  58.     move.b    IDEER,d0    ; else d0.b = error bits
  59.     bra.s    .3        ; return with error
  60.  
  61. .else                ; for driver code
  62.     bne.s    .3        ; if error, return
  63. .endif    ;!DRIVER
  64.  
  65. .2:    btst    #DRQ,d0        ; else DRQ?
  66.     bne.s    .3        ; if so, just return
  67.     moveq    #0,d0        ; else return OK
  68. .3:    rts            ; return status or error code
  69.  
  70.  
  71.  
  72. ;+
  73. ; ideread() - reads from 1 to 256 sectors as specified in the Task File,
  74. ;        beginning at the specified sector.
  75. ;        - sector count equal to 0 requests 256 sectors.
  76. ;
  77. ; ideread(nhd, nspt, sectnum, count, buf, pdev)
  78. ; WORD    nhd;        4(sp).w        ; # of data heads on pdev
  79. ; WORD    nspt;        6(sp).w        ; # of sectors per track
  80. ; LONG    sectnum;    8(sp).l        ; logical block address
  81. ; WORD    count;        $c(sp).w    ; # of sectors to read
  82. ; BYTE    *buf;        $e(sp).l    ; $f(sp)=high $10(sp)=mid $11(sp)=low
  83. ; WORD    pdev;        $12(sp).w    ; physical device number
  84. ;-
  85.     .globl    _ideread
  86. _ideread:
  87.     bsr    set_dhcs    ; set physical address
  88.     move.l    $e(sp),a0    ; a0 -> buffer to read into
  89.     move.b    $d(sp),IDESC    ; set sector count
  90.  
  91.     move.w    $c(sp),d1    ; d1.w = # of sectors to read
  92.     subq    #1,d1        ; dbra likes one less
  93.  
  94.     tst.b    _useblit    ; BLiTTER exists?
  95.     beq.s    .0        ; if not, don't use it
  96.     moveq    #0,d0        ; else it's a read
  97.     bsr    initblit    ; initialize the BLiTTER
  98.  
  99. .0:    move.b    #0,IDEDOR    ; enable interrupt
  100.     move.b    #READ,IDECR    ; set command code
  101. .1:    bsr    w4int        ; wait for interrupt
  102.     tst.w    d0        ; successful?
  103.     bmi.s    .2        ; if timed-out, return
  104.     btst    #DRQ,d0        ; DRQ?
  105.     beq.s    .2        ; if not, return
  106.                 ; else
  107.     bsr    readbuf        ; transfer data
  108.     dbra    d1,.1        ; go wait for next interrupt
  109.     moveq    #0,d0        ; everything is fine
  110. .2:    rts
  111.  
  112.  
  113. ;+
  114. ; idewrite() - writes from 1 to 256 sectors as specified in the Task File,
  115. ;        beginning at the specified sector.
  116. ;         - sector count equal to 0 requests 256 sectors.
  117. ;
  118. ; idewrite(nhd, nspt, sectnum, count, buf, pdev)
  119. ; WORD    nhd;        4(sp).w        ; # of data heads on pdev
  120. ; WORD    nspt;        6(sp).w        ; # of sectors per track
  121. ; LONG    sectnum;    8(sp).l        ; logical block address
  122. ; WORD    count;        $c(sp).w    ; # sectors to read
  123. ; BYTE    *buf;        $e(sp).l    ; $f(sp)=high $10(sp)=mid $11(sp)=low
  124. ; WORD    pdev;        $12(sp).w    ; physical device number
  125. ;-
  126.     .globl    _idewrite
  127. _idewrite:    
  128.     bsr    set_dhcs    ; set physical address
  129.     move.l    $e(sp),a0    ; a0 -> buffer to write from
  130.     move.b    $d(sp),IDESC    ; set sector count
  131.  
  132.     move.w    $c(sp),d1    ; d1.w = # of sectors to read
  133.     subq    #1,d1        ; dbra likes one less
  134.  
  135.     tst.b    _useblit    ; BLiTTER exists?
  136.     beq.s    .0        ; if not, don't use it
  137.     moveq    #1,d0        ; it's a write
  138.     bsr    initblit    ; initialize the BLiTTER
  139.  
  140. .0:    move.b    #0,IDEDOR    ; enable interrupt
  141.     move.b    #WRITE,IDECR    ; set command code
  142. .1:    btst.b    #DRQ,IDEASR    ; DRQ?
  143.     beq.s    .1        ; if not, wait longer
  144.  
  145. .2:    bsr    wrtbuf        ; transfer data
  146.     bsr    w4int        ; wait for interrupt
  147.     tst.w    d0        ; successful?
  148.     bmi.s    .3        ; if timed-out, return
  149.     btst    #DRQ,d0        ; DRQ?
  150.     beq.s    .3        ; if not, return
  151.     dbra    d1,.2        ; else go transfer data
  152.     moveq    #0,d0        ; everything is fine
  153. .3:    rts
  154.  
  155.  
  156. ;+
  157. ; set_dhcs() - convert a logical block address into a physical address.
  158. ;         - set drive #, head #, cylinder # and sector # in task file.
  159. ;
  160. ; Passed:
  161. ;    8(sp).w = nhd = # of data heads
  162. ;    $a(sp).w = nspt = # of sectors per track
  163. ;    $c(sp).l = logical block address
  164. ;    $16(sp).w = physical unit #
  165. ;-
  166. set_dhcs:
  167.     move.l    $c(sp),d1    ; d1.l = logical block address
  168.     move.w    8(sp),d2    ; d2.w = # of data heads
  169.     move.w    $a(sp),d0    ; d0.w = # of sectors per track
  170.     mulu    d0,d2        ; d2.l = # of sectors per cylinder
  171.                 ;      = # heads * # of sectors per track
  172.     divu.w    d2,d1        ; d1.w = cylinder #
  173.                 ;      = log block addr / #spc
  174.     move.b    d1,IDECL    ; set cylinder low
  175.     lsr.l    #8,d1        ; d1.b = cylinder high
  176.     move.b    d1,IDECH    ; set cylinder high
  177.     lsr.l    #8,d1        ; d1.l = sector # within the cyl
  178.     divu.w    d0,d1        ; d1.w = head #
  179.                 ;      = sector # within cyl / #spt
  180.     move.w    $16(sp),d0    ; d0.w = physical unit #
  181.     andi.b    #7,d0        ; mask off flags from physical unit #
  182.     lsl.b    #4,d0        ; shift unit # to place
  183.     or.b    d0,d1        ; or in drive #
  184.     move.b    d1,IDESDH    ; set drive and head #
  185.     swap    d1        ; d1.w = sector # (base 0)
  186.     addq.w    #1,d1        ;      = sector # + 1 (base 1)
  187.     move.b    d1,IDESN    ; set sector #
  188.     rts
  189.  
  190. ;+
  191. ; identify() - allows the Host to receive parameter information from
  192. ;           the drive.
  193. ;
  194. ; identify(pdev, buf)
  195. ; WORD    pdev;    4(sp).w        ; physical unit #
  196. ; BYTE    *buf;    6(sp).l        ; buffer to put data
  197. ;-
  198.     .globl    _identify
  199. _identify:
  200.     move.w    4(sp),d0    ; d0 = physical unit #
  201.     andi.b    #7,d0        ; mask off flags (if any)
  202.     lsl.b    #4,d0        ; shift unit # to place
  203.     move.b    d0,IDESDH    ; set drive #
  204.     move.l    6(sp),a0    ; a0 -> buffer
  205.  
  206.     tst.b    _useblit    ; BLiTTER exists?
  207.     beq.s    .0        ; if not, no need to init it
  208.     moveq    #0,d0        ; it's a read
  209.     bsr    initblit    ; initialize the BLiTTER
  210.  
  211. .0:    move.b    #0,IDEDOR    ; enable interrupt
  212.     move.b    #IDENTIFY,IDECR    ; set command code
  213.     bsr    w4int        ; wait for interrupt
  214.     tst.w    d0        ; successful?
  215.     bmi.s    .1        ; if timed-out, return
  216.     btst    #DRQ,d0        ; DRQ?
  217.     beq.s    .1        ; if not, return with error
  218.  
  219.     bsr    readbuf        ; read data
  220.     moveq    #0,d0        ; everything is fine
  221. .1:    rts 
  222.  
  223.  
  224. ;+
  225. ; awto() - set drive to Active mode with timeout counter (in 5s increments)
  226. ;
  227. ; awto(pdev, timeout)
  228. ; WORD    pdev;        4(sp).w        ; physical unit #
  229. ; WORD    timeout;    6(sp).w
  230. ;-
  231.     .globl    _awto
  232. _awto:    
  233.     move.w    4(sp),d0    ; d0 = physical unit #
  234.     andi.b    #7,d0        ; mask off flags (if any)
  235.     lsl.b    #4,d0        ; shift unit # to place
  236.     move.b    d0,IDESDH    ; set drive #
  237.     move.b    7(sp),IDESC    ; set timeout counter
  238.     move.b    #AWTO,IDECR    ; set command code
  239.     bra    w4int        ; go wait for interrupt
  240.  
  241.  
  242. ;+
  243. ; readbuf() - reads 512 bytes (128 longs) of data from the sector
  244. ;        buffer.
  245. ;
  246. ; Comments:
  247. ;    A tower of 8 move.l is used to try to speed up the transfer.
  248. ;
  249. ; Passed:
  250. ;    a0.l = buffer to store data read from sector buffer
  251. ;
  252. ;    if BLiTTER code
  253. ;    a1.l = base address of BLiTTER
  254. ;-
  255. readbuf:
  256.     tst.b    _useblit    ; BLiTTER exists?
  257.     beq.s    .0        ; if not, do programmed IO
  258.     move.w    #1,YCNT(a1)    ; one destination line
  259.     move.b    #$80,BUSY(a1)    ; start the BLiTTER
  260.     bsr    restart
  261.     addq.l    #2,DESTADDR(a1)    ; advance to next word of destination
  262.     rts
  263.                 ; Programmed IO
  264. .0:    moveq    #15,d0        ; d0 = (# of longs to read / 8) - 1
  265.     lea    IDEDR,a1    ; a1 -> data bus
  266. .1:    move.l    (a1),(a0)+    ; read data from bus
  267.     move.l    (a1),(a0)+    ; read data from bus
  268.     move.l    (a1),(a0)+    ; read data from bus
  269.     move.l    (a1),(a0)+    ; read data from bus
  270.     move.l    (a1),(a0)+    ; read data from bus
  271.     move.l    (a1),(a0)+    ; read data from bus
  272.     move.l    (a1),(a0)+    ; read data from bus
  273.     move.l    (a1),(a0)+    ; read data from bus
  274.     dbra    d0,.1        ; repeat until all done
  275.     rts
  276.  
  277.  
  278. ;+
  279. ; wrtbuf() - writes 512 bytes (128 longs) of data to sector buffer.
  280. ;
  281. ; Passed:
  282. ;    a0.l = buffer with data to write to sector buffer
  283. ;-
  284. wrtbuf:
  285.     tst.b    _useblit    ; BLiTTER exists?
  286.     beq.s    .0        ; if not, do programmed IO
  287.     move.w    #1,YCNT(a1)    ; one destination line
  288.     move.b    #$80,BUSY(a1)    ; start the BLiTTER
  289.     bsr    restart
  290.     addq.l    #2,SRCADDR(a1)    ; advance to next word of source
  291.     rts
  292.                 ; Programmed IO
  293. .0:    moveq    #15,d0        ; d0 = (# longs to write / 8) - 1
  294.     lea    IDEDR,a1    ; a1 -> data bus
  295. .1:    move.l    (a0)+,(a1)    ; write data to bus
  296.     move.l    (a0)+,(a1)    ; write data to bus
  297.     move.l    (a0)+,(a1)    ; write data to bus
  298.     move.l    (a0)+,(a1)    ; write data to bus
  299.     move.l    (a0)+,(a1)    ; write data to bus
  300.     move.l    (a0)+,(a1)    ; write data to bus
  301.     move.l    (a0)+,(a1)    ; write data to bus
  302.     move.l    (a0)+,(a1)    ; write data to bus
  303.     dbra    d0,.1        ;  repeat until all done
  304.     rts
  305.  
  306.  
  307. ;+
  308. ; drvxst() - test if an IDE drive exists
  309. ;
  310. ; Returns:  0 - if drive does not exist
  311. ;        1 - if drive exists
  312. ;-
  313.     .globl    _drvxst
  314. _drvxst:
  315.     move.w    #$5a5a,IDEDR
  316.     move.w    IDEDR,d0
  317.     cmpi.w    #$5a5a,d0
  318.     bne.s    .0
  319.     moveq    #1,d0        ; else, drive exists
  320.     rts
  321. .0:    moveq    #0,d0        ; drive does not exist
  322.     rts
  323.  
  324.  
  325. ;+
  326. ; initblit() - initialize the BLiTTER chip for 512 bytes I/O transfer
  327. ;
  328. ; Passed:
  329. ;    a0.l = destination address if read; source address if write
  330. ;    d0.w = flag to tell whether it's a read or a write
  331. ;-
  332. initblit:
  333.     lea    bBLiTTER,a1        ; a1 -> BLiTTER register map
  334.     tst.b    d0            ; read or write?
  335.     bne.s    ib0            ; (write)
  336.     move.l    #IDEDR,SRCADDR(a1)    ; source addr = IDE data register
  337.     move.l    a0,DESTADDR(a1)        ; destination addr = given buffer
  338.     move.w    #2,DESTXINC(a1)        ; words read
  339.     moveq    #0,d0
  340.     move.w    d0,SRCXINC(a1)        ; never increment source X
  341.     bra.s    ib1
  342.                     ; initialize BLiTTER to write to disk
  343. ib0:    move.l    a0,SRCADDR(a1)        ; source addr = write buffer
  344.     move.l    #IDEDR,DESTADDR(a1)    ; destination addr = IDE data reg
  345.     move.w    #2,SRCXINC(a1)        ; words write
  346.     moveq    #0,d0
  347.     move.w    d0,DESTXINC(a1)        ; never increment destination X
  348.  
  349. ib1:    move.w    d0,SRCYINC(a1)        ; never increment source Y
  350.     move.w    d0,DESTYINC(a1)        ; never increment destination Y
  351.     move.b    d0,SKEW(a1)        ; no skew
  352.     moveq    #$ff,d0
  353.     move.l    d0,ENDMASK1(a1)        ; change all bits at destination
  354.     move.w    d0,ENDMASK3(a1)        ; change all bits at destination
  355.     move.w    #$203,HOP(a1)        ; set HOP and OP to source
  356.     move.w    #256,XCNT(a1)        ; num of words to transfer
  357.     rts
  358.  
  359.  
  360. ;+
  361. ; restart() - restart the BLiTTER
  362. ;
  363. ; Passed:
  364. ;    a1.l = base address of BLiTTER
  365. ;-
  366. restart:
  367.     nop
  368.     tas    BUSY(a1)    ; restart BLiTTER and test if busy
  369.     bmi.s    restart        ; quit if not busy
  370.     rts
  371.  
  372.  
  373. ;+
  374. ; gcparm() - get current drive parameters
  375. ;
  376. ; gcparm(buf)
  377. ; char    *buf;    $4(sp).l    /* -> data returned by identify() */
  378. ;
  379. ; Returns:
  380. ;    d0.w = # of default cylinders
  381. ;    d1.w = # of default heads
  382. ;    d2.w = # of default sectors per track
  383. ;-
  384.     .globl    _gcparm
  385. _gcparm:
  386.     move.l    4(sp),a0    ; a0 -> data buffer
  387.     add.l    #CONMDL,a0    ; a0 -> where Conner model number is
  388.     move.l    a0,-(sp)
  389.     pea    cp2024
  390.     move.w    #6,-(sp)
  391.     bsr    strcmp        ; compare model# with "CP2024"
  392.     adda    #10,sp        ; clean up stack
  393.     tst.w    d0        ; is unit the CP2024 (Kato 20Mb)?
  394.     bne.s    gcp0        ; if not, handle the normal way
  395.                 ; else return default values of CP2024
  396.     move.w    #CP20NCYL,d0    ; d0.w = # of cylinders
  397.     move.w    #CP20NHEAD,d1    ; d1.w = # of heads
  398.     move.w    #CP20NSPT,d2    ; d2.w = # of spt
  399.     bra.s    gcpend
  400.  
  401. gcp0:    move.l    4(sp),a0
  402.     move.w    NCYL(a0),d0    ; d0.w = # of cylinders
  403.     move.w    NHEAD(a0),d1    ; d1.w = # of heads
  404.     move.w    NSPT(a0),d2    ; d2.w = # of sectors per track
  405.  
  406. gcpend:    rts
  407.  
  408.  
  409.  
  410. conner:    dc.b    "Conner",0
  411. .even
  412. cp2024:    dc.b    "CP2024",0
  413. .even
  414.  
  415.  
  416. ;+
  417. ; strcmp() - compare two strings
  418. ;
  419. ; Passed:
  420. ;    4(sp).w  = n (# of bytes to compare)
  421. ;    6(sp).l  = address of first string
  422. ;    10(sp).l = address of second string
  423. ;
  424. ; Returns:
  425. ;    d0.w = 0    if first n bytes of the 2 strings are the same
  426. ;         = non-0    otherwise
  427. ;-
  428. strcmp:    movem.l    d1/a0-a1,-(sp)    ; save registers d1, a0 and a1
  429.     move.w    16(sp),d1    ; d1 = byte count
  430.     subq.w    #1,d1        ; dbra likes one less
  431.     move.l    18(sp),a0    ; a0 -> string 1
  432.     move.l    22(sp),a1    ; a1 -> string 2
  433.     moveq    #1,d0        ; assume strings are not the same
  434. .0:    cmpm.b    (a0)+,(a1)+    ; characters the same?
  435.     bne.s    .1        ; if not, return
  436.     dbra    d1,.0        ; else compare next character
  437.     moveq    #0,d0        ; the strings are the same
  438. .1:    movem.l    (sp)+,d1/a0-a1    ; restore registers d1, a0 and a1
  439.     rts
  440.  
  441.  
  442. .if    !DRIVER
  443.  
  444. ;+
  445. ; recal() - moves the R/W heads from anywhere on the disk to cylinder 0.
  446. ;
  447. ; recal(pdev)
  448. ; WORD    pdev;    $4(sp).w
  449. ;-
  450.     .globl    _recal
  451. _recal:    move.w    4(sp),d0    ; d0 = physical unit #
  452.     andi.b    #7,d0        ; mask off flags (if any)
  453.     lsl.b    #4,d0        ; shift unit # to place
  454.     move.b    d0,IDESDH    ; write drive #
  455.     move.b    #0,IDEDOR    ; enable interrupt
  456.     move.b    #RECAL,IDECR    ; write command code
  457.     bra    w4int        ; go wait for interrupt
  458.  
  459.  
  460. ;+
  461. ; verify() - functions similarly to read() except that no data is
  462. ;         transferred to the host.
  463. ;-
  464.     .globl    _verify
  465. _verify:
  466.     move.w    $e(sp),d0    ; d0.w = physical unit #
  467.     move.l    4(sp),d1    ; d1.l = starting logical sector #
  468.     bsr    set_dhcs    ; set drive#, head#, cylinder# and sector#
  469.     move.l    $a(sp),a0    ; a0 -> buffer to write from
  470.     move.b    9(sp),IDESC    ; set sector count
  471.     move.b    #0,IDEDOR    ; enable interrupt
  472.     move.b    #VERIFY,IDECR    ; set command code
  473. .0:    bsr    w4int        ; wait for interrupt
  474.     bne.s    .1        ; if has error, return
  475.     tst.b    IDESC        ; more to verify?
  476.     bne.s    .0        ; if so, continue
  477.     moveq    #0,d0        ; everything's fine
  478. .1:    rts
  479.  
  480.  
  481. ;+
  482. ; fmtunt() - formats a unit
  483. ;       - always formats sectors as good ones.
  484. ;       - interleave 1:1.
  485. ;
  486. ; fmtunt(pdev)
  487. ; WORD    pdev;    4(sp).w
  488. ;-
  489.     .globl    _fmtunt
  490. _fmtunt:
  491.     move.l    d3,-(sp)    ; save d3
  492.     move.w    8(sp),-(sp)    ; set selected unit to the appropiate
  493.     bsr    setmode        ;  mode and get drive parameters in d1-d3
  494.     addq    #2,sp        ; clean up stack
  495.     tst.w    d0        ; setmode() ok?
  496.     bne    .5        ; if not, return
  497.                 ; else fill format data
  498.     bsr    clrsbuf        ; clear scratch buffer
  499.     moveq    #1,d0        ; d0 = sector # (starts with sector 1)
  500.     lea    sbuf,a1        ; a1 -> _identify() data buffer
  501. .0:    move.b    d0,(a1)+    ; set sector #
  502.     clr.b    (a1)+        ; format sector good
  503.     addq.b    #1,d0        ; next sector #
  504.     cmp.b    d0,d3        ; all sector # set?
  505.     bcc.s    .0        ; if not, continue
  506.                 ; format unit
  507.     move.w    8(sp),d3    ; d3.w = physical unit #
  508.     andi.b    #7,d3        ; mask off flags (if any)
  509.     lsl.b    #4,d3        ; shift physical unit # into place
  510.     move.b    d3,IDESDH    ; set physical unit #
  511.     subq.w    #1,d1        ; dbra likes one less
  512.     subq.w    #1,d2        ; dbra likes one less
  513.     move.w    d2,d3        ; d3 = # heads - 1
  514.     lea    sbuf,a0        ; a0 -> format data
  515. .1:    move.w    d3,d2        ; reinitialize head number for next cylinder
  516. .2:    movem.l    d1-d2/a0,-(sp)    ; save cylinder and head count
  517.     bsr    _fmttrk        ; format track of current cylinder and head
  518.     bne.s    .4        ; if fail, return
  519. .3:    movem.l    (sp)+,d1-d2/a0    ; restore cylinder and head count
  520.     dbra    d2,.2        ; for all heads
  521.     dbra    d1,.1        ; for all cylinders
  522.     moveq    #0,d0        ; everything's fine
  523.     bra.s    .5        ; and return
  524. .4:    adda.l    #12,sp        ; else clean up stack
  525. .5:    move.l    (sp)+,d3    ; restore d3
  526.     rts
  527.  
  528.  
  529.  
  530. ;+
  531. ; setmode() - set the unit to its default mode and return the default
  532. ;        drive parameters.
  533. ;
  534. ; setmode(pdev)
  535. ; WORD    pdev;    $4(sp).w
  536. ;
  537. ; Returns:
  538. ;    d0.w = 0    if successful
  539. ;         = non-0    if failed
  540. ;    d1.w = # of default cylinders
  541. ;    d2.w = # of default heads
  542. ;    d3.w = # of default sectors per track
  543. ;
  544. ; Comments:
  545. ;    This routine distinguishes the Conner drives from other vendors'
  546. ; because Conner saves their default values in a reserved area. (Sigh)
  547. ; Furthermore, since the default parameters are not stored on the Conner 
  548. ; CP2024 (20Mb) drives at all, they are being hardwired into the code. 
  549. ; (I know, it's terrible!)
  550. ;-
  551. setmode:
  552.     pea    sbuf        ; scratch buffer
  553.     move.w    8(sp),-(sp)    ; physical unit #
  554.     bsr    _identify    ; identify(pdev, buf)
  555.     addq.w    #6,sp        ; clean up stack
  556.     tst.w    d0        ; successful?
  557.     bne    smend        ; if not, return
  558.                 ; else 
  559.     lea    sbuf,a1        ; a1 -> data buffer
  560.     move.l    #sbuf+MDLNUM,-(sp)
  561.     pea    conner
  562.     move.w    #6,-(sp)
  563.     bsr    strcmp        ; compare model# with "Conner"
  564.     adda    #10,sp        ; clean up stack
  565.     tst.w    d0        ; is unit a Conner drive?
  566.     bne.s    other        ; if not, handle the normal way
  567.                 ; else
  568.     move.l    #sbuf+CONMDL,-(sp)
  569.     pea    cp2024
  570.     move.w    #6,-(sp)
  571.     bsr    strcmp        ; compare model# with "CP2024"
  572.     adda    #10,sp        ; clean up stack
  573.     tst.w    d0        ; is unit the CP2024 (Kato 20Mb)?
  574.     bne.s    nkato        ; if not, parms at reserved area
  575.                 ; else return default values of CP2024
  576.     move.w    #CP20NCYL,d1    ; d1.w = # of cylinders
  577.     move.w    #CP20NHEAD,d2    ; d2.w = # of heads
  578.     move.w    #CP20NSPT,d3    ; d3.w = # of spt
  579.     bra.s    smend        ; no need to init parm, just return
  580.  
  581.                 ; for other Conner drives
  582. nkato:    move.w    CPNCYL(a1),d1    ; get parameters at Conner
  583.     moveq    #0,d2        ;   reserved location
  584.     move.b    CPNHEAD(a1),d2
  585.     moveq    #0,d3
  586.     move.b    CPNSPT(a1),d3
  587.     bra.s    sminit        ; go do initparm
  588.  
  589. other:    move.w    NCYL(a1),d1    ; d1.w = # of cylinders
  590.     move.w    NHEAD(a1),d2    ; d2.w = # of heads
  591.     move.w    NSPT(a1),d3    ; d3.w = # of sectors per track
  592.  
  593. sminit:    movem.l    d1-d3,-(sp)    ; save drive parameters
  594.     move.w    d3,-(sp)    ; sectors per track
  595.     move.w    d2,-(sp)    ; # of heads
  596.     move.w    20(sp),-(sp)    ; physical unit #
  597.     bsr    _initparm    ; set drive to default mode
  598.     addq.w    #6,sp        ; clean up stack
  599.     movem.l    (sp)+,d1-d3    ; restore drive parameters
  600.  
  601. smend:    rts
  602.  
  603.  
  604. ;+
  605. ; clrsbuf() - clear the scratch buffer
  606. ;-
  607. clrsbuf:
  608.     movem.l    d0/a0,-(sp)    ; save d0 and a0
  609.     lea    sbuf,a0        ; a0 -> scratch buffer
  610.     move.w    #127,d0        ; d0 = counter
  611. .0:    clr.l    (a0)+        ; clear 4 bytes
  612.     dbra    d0,.0        ; repeat until done
  613.     movem.l    (sp)+,d0/a0    ; restore d0 and a0
  614.     rts
  615.  
  616.  
  617. ;+
  618. ; fmttrk() - formats a track with format data provided.
  619. ;
  620. ; Passed:
  621. ;    d1.w = cylinder #
  622. ;    d2.w = head #
  623. ;    a0.l -> format data
  624. ;-
  625.     .globl    _fmttrk
  626. _fmttrk:
  627.     andi.b    #$f0,IDESDH    ; erase previous head #
  628.     or.b    d2,IDESDH    ; set new head #
  629.     move.b    d1,IDECL    ; set cylinder low
  630.     lsr.w    #8,d1        ; d0.b = cylinder high
  631.     move.b    d1,IDECH    ; set cylinder high
  632.     move.b    #0,IDEDOR    ; enable interrupt
  633.  
  634.     tst.b    _useblit    ; use BLiTTER?
  635.     beq.s    .0        ; if not, no need to init it
  636.     moveq    #1,d0        ; write through BLiTTER
  637.     bsr    initblit    ; initialize the BLiTTER
  638.  
  639. .0:    move.b    #FMTTRK,IDECR    ; set command code
  640. .1:    btst.b    #DRQ,IDEASR    ; DRQ?
  641.     beq.s    .1        ; if not, wait longer
  642.  
  643.     bsr    wrtbuf        ; write format data to sector buffer
  644.     bra    w4int
  645.  
  646.  
  647. ;+
  648. ; seek() - initiates a seek to the track and selects the head 
  649. ;       specified in the Task File.
  650. ;
  651. ; seek(pdev, head, cyl)
  652. ; WORD    pdev;    $4(sp).w
  653. ; WORD    head;    $6(sp).w
  654. ; WORD    cyl;    $8(sp).w
  655. ;-
  656.     .globl    _seek
  657. _seek:    move.w    4(sp),d0    ; d0 = physical unit #
  658.     andi.b    #7,d0        ; mask off flags
  659.     lsl.b    #4,d0        ; shift unit # to place
  660.     or.b    7(sp),d0    ; b4 of d0 = drive #; b3-b0 of d0 = head #;
  661.     move.b    d0,IDESDH    ; set drive and head #
  662.     move.b    #0,IDEDOR    ; enable interrupt
  663.     move.b    9(sp),IDECL    ; set cylinder low
  664.     move.b    8(sp),IDECH    ; set cylinder high
  665.     move.b    #SEEK,IDECR    ; set command code
  666.     bra    w4int        ; go wait for interrupt
  667.  
  668.  
  669. ;+
  670. ; diag() - performs the internal diagnostic tests implemented by 
  671. ;       the drive.
  672. ;-
  673.     .globl    _diag
  674. _diag:    move.b    #0,IDEDOR    ; enable interrupt
  675.     move.b    #DIAG,IDECR    ; set command code
  676.     bra    w4int
  677.  
  678.  
  679. ;+
  680. ; initparm() - enables the host to set the head switch and cylinder
  681. ;           increment points for multiple sector operations.
  682. ;
  683. ; initparm(pdev, head, spt)
  684. ; WORD     pdev;    4(sp).w
  685. ; WORD    head;    6(sp).w
  686. ; WORD    spt;    8(sp).w
  687. ;-
  688.     .globl    _initparm
  689. _initparm:
  690.     move.w    4(sp),d0    ; d0 = physical unit #
  691.     andi.b    #7,d0        ; mask off flags
  692.     lsl.w    #4,d0        ; shift it into place
  693.     move.b    d0,IDESDH    ; set physical unit #
  694.     move.w    6(sp),d0    ; d0 = # of heads
  695.     subq.b    #1,d0        ; maximum head #
  696.     or.b    d0,IDESDH    ; set head #
  697.     move.b    9(sp),IDESC    ; set sectors per track
  698.     move.b    #0,IDEDOR    ; enable interrupt
  699.     move.b    #INITPARM,IDECR    ; set command code
  700.     bra    w4int        ; go wait for interrupt
  701.  
  702.  
  703. ;+
  704. ; rsbuf() - allows the Host to read the current contents of the
  705. ;        drive's sector buffer.
  706. ;
  707. ; rsbuf(pdev, buf)
  708. ; WORD    pdev;    4(sp).w
  709. ; BYTE    *buf;    6(sp).l
  710. ;-
  711.     .globl    _rsbuf
  712. _rsbuf:    move.w    4(sp),d0    ; d0 = physical unit #
  713.     andi.b    #7,d0        ; mask off flags (if any)
  714.     lsl.w    #4,d0        ; shift it into place
  715.     move.b    d0,IDESDH    ; set physical unit #
  716.     move.l    6(sp),a0    ; a0 -> buffer
  717.     move.w    #256,d1
  718.  
  719.     tst.b    _useblit    ; BLiTTER exists?
  720.     beq.s    .0        ; if not, don't use it
  721.     moveq    #0,d0        ; it's a read
  722.     bsr    initblit    ; initialize the BLiTTER
  723.  
  724. .0:    move.b    #0,IDEDOR    ; enable interrupt
  725.     move.b    #RSBUF,IDECR    ; set command code
  726.     bsr    w4int        ; go wait for interrupt
  727.     tst.w    d0        ; successful?
  728.     bmi.s    .1        ; if timed-out, return
  729.     btst    #DRQ,d0        ; DRQ?
  730.     beq.s    .1        ; if not, return with error
  731.  
  732.     bsr    readbuf        ; read data
  733.     moveq    #0,d0        ; everything is fine
  734. .1:    rts 
  735.  
  736.  
  737. ;+
  738. ; wsbuf() - allows the Host to overwrite the contents of the drive's
  739. ;        sector buffer.
  740. ;
  741. ; wsbuf(pdev, buf)
  742. ; WORD    pdev;    4(sp).w
  743. ; BYTE    *buf;    6(sp).l
  744. ;-
  745.     .globl    _wsbuf
  746. _wsbuf:    move.w    4(sp),d0    ; d0 = physical unit #
  747.     andi.b    #7,d0        ; mask off flags (if any)
  748.     lsl.w    #4,d0        ; shift it into place
  749.      move.b    d0,IDESDH    ; set physical unit #
  750.     move.l    6(sp),a0    ; a0 -> buffer
  751.     move.w    #256,d0        ; d0 = word count
  752.  
  753.     tst.b    _useblit    ; BLiTTER exists?
  754.     beq.s    .0        ; if not, don't use it
  755.     moveq    #0,d0        ; it's a read
  756.     bsr    initblit    ; initialize the BLiTTER
  757.  
  758. .0:    move.b    #WSBUF,IDECR    ; set command code
  759. .1:    btst    #DRQ,IDESR    ; DRQ?
  760.     beq.s    .1        ; if not, wait some more
  761.  
  762.     bsr    wrtbuf        ; write data
  763.     moveq    #0,d0        ; everything is fine
  764.     rts
  765.  
  766.  
  767. ;+
  768. ; standby() - set drive to Standby mode
  769. ;
  770. ; standby(pdev)
  771. ; WORD    pdev;    4(sp).w        ; physical unit #
  772. ;-
  773.     .globl    _standby
  774. _standby:
  775.     move.w    4(sp),d0    ; d0 = physical unit #
  776.     andi.b    #7,d0        ; mask off flags (if any)
  777.     lsl.b    #4,d0        ; shift unit # to place
  778.     move.b    d0,IDESDH    ; set drive #
  779.     move.b    #STANDBY,IDECR    ; set command code
  780.     bra    w4int        ; go wait for interrupt
  781.  
  782.  
  783. ;+
  784. ; active() - set drive to Active mode
  785. ;
  786. ; active(pdev)
  787. ; WORD    pdev;    4(sp).w        ; physical unit #
  788. ;-
  789.     .globl    _active
  790. _active:
  791.     move.w    4(sp),d0    ; d0 = physical unit #
  792.     andi.b    #7,d0        ; mask off flags (if any)
  793.     lsl.b    #4,d0        ; shift unit # to place
  794.     move.b    d0,IDESDH    ; set drive #
  795.     move.b    #ACTIVE,IDECR    ; set command code
  796.     bra    w4int        ; go wait for interrupt
  797.  
  798.  
  799. ;+
  800. ; sbwto() - set drive to Standby mode with timeout counter (in 5s increments)
  801. ;
  802. ; sbwto(pdev, timeout)
  803. ; WORD    pdev;        4(sp).w        ; physical unit #
  804. ; WORD    timeout;    6(sp).w
  805. ;-
  806.     .globl    _sbwto
  807. _sbwto:    
  808.     move.w    4(sp),d0    ; d0 = physical unit #
  809.     andi.b    #7,d0        ; mask off flags (if any)
  810.     lsl.b    #4,d0        ; shift unit # to place
  811.     move.b    d0,IDESDH    ; set drive #
  812.     move.b    7(sp),IDESC    ; set timeout counter
  813.     move.b    #SBWTO,IDECR    ; set command code
  814.     bra    w4int        ; go wait for interrupt
  815.  
  816.  
  817. ;+
  818. ; ssc() - set sector count wrt current mode of drive
  819. ;
  820. ; ssc(pdev)
  821. ; WORD    pdev;    4(sp).w        ; physical unit #
  822. ;-
  823.     .globl    _ssc
  824. _ssc:    
  825.     move.w    4(sp),d0    ; d0 = physical unit #
  826.     andi.b    #7,d0        ; mask off flags (if any)
  827.     lsl.b    #4,d0        ; shift unit # to place
  828.     move.b    d0,IDESDH    ; set drive #
  829.     move.b    #SSC,IDECR    ; set command code
  830.     bra    w4int        ; go wait for interrupt
  831.  
  832.  
  833. ;+
  834. ; sbres() - set drive to Standby mode.
  835. ;      - drive will not wake up until reset is sent to drive
  836. ;
  837. ; sbres(pdev)
  838. ; WORD    pdev;    4(sp).w        ; physical unit #
  839. ;-
  840.     .globl    _sbres
  841. _sbres:    
  842.     move.w    4(sp),d0    ; d0 = physical unit #
  843.     andi.b    #7,d0        ; mask off flags (if any)
  844.     lsl.b    #4,d0        ; shift unit # to place
  845.     move.b    d0,IDESDH    ; set drive #
  846.     move.b    #SBRES,IDECR    ; set command code
  847.     bra    w4int        ; go wait for interrupt
  848.  
  849.  
  850. ;+
  851. ; slave() - test if the slave drive exists
  852. ;
  853. ; Returns: 0 - if slave does not exist
  854. ;       1 - if slave exists
  855. ;-
  856.     .globl    _slave
  857. _slave:    moveq    #0,d0        ; assume slave does NOT exist
  858.     bset.b    #4,IDESDH    ; set drive bit to 1 (slave)
  859.     btst.b    #DRDY,IDESR    ; is slave ready?
  860.     beq.s    .0        ; if not, no slave
  861.     moveq    #1,d0        ; else, slave exists
  862. .0:    rts
  863.  
  864.  
  865. ;+
  866. ; _iderdy() - test if the IDE drive is ready
  867. ;
  868. ; Passed:
  869. ;    d0.b = IDE drive unit #
  870. ;
  871. ; Returns: 0 - if drive is NOT ready
  872. ;       1 - if drive is ready
  873. ;-
  874.     .globl    _iderdy
  875. _iderdy:
  876.     andi.b    #7,d0        ; mask off flags (if any)
  877.     lsl.b    #4,d0        ; shift unit # to place
  878.     move.b    d0,IDESDH    ; set drive #
  879.     move.b    #$50,d1        ; ready status
  880.     move.l    #IDERDY,d0    ; set up timer
  881.     add.l    _hz_200,d0
  882. ir0:    cmp.b    IDEASR,d1    ; is drive ready and not busy?
  883.     beq.b    ir1        ; if so, return with drive ready
  884.     cmp.l    _hz_200,d0    ; time-out yet?
  885.     bcc.b    ir0        ; if not, wait longer
  886.     moveq    #0,d0        ; else return drive NOT ready
  887.     rts
  888. ir1:    moveq    #1,d0        ; else, drive is ready
  889.     rts
  890.  
  891.  
  892. .data
  893. sbuf:    dcb.b    512,0        ; scratch buffer
  894.  
  895. .endif    ;!DRIVER
  896.  
  897.  
  898.